package com.ruan.controller;
import com.ruan.common.R;
import com.ruan.common.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.UUID;

//进行图片的上传和下载
@RestController
@RequestMapping("/common")
@Slf4j
public class CommonController {

    @Value("${kejiu.path}")//必须是org.springframework.beans.factory.annotation提供的Value
    private String basePath;

    //图片上传(io流的transferTo方法实现)
    @PostMapping("/upload")
    public R<String> upload(MultipartFile file){
//file必须跟前端upload.html页面的检查-Network-Headers右边的Payload-Form Data-Content-Disposition:name="file"一致
//file是一个临时文件，需要转存到指定位置，否则本次请求完成后临时文件会删除
        log.info("上传的文件是"+file.toString());
//获取上传文件的原始文件名
        String originalFilename = file.getOriginalFilename();//abc.jpg
        //log.info("原文件是"+originalFilename);
        //截取.jpg等文件后缀(suffix)
        String suffix = originalFilename.substring(originalFilename.lastIndexOf("."));//从最后的 . 开始截

        //System.out.println("截到了吗"+suffix);
        //使用UUID重新生成文件名，防止文件名称重复，造成文件覆盖
        String filename = UUID.randomUUID().toString() + suffix;//xfdccdd.jpg

        //创建一个目录对象
        File dir = new File(basePath);
        //判断是否存在该目录
        if(!dir.exists()){
            //目录不存在，需要创建
            dir.mkdirs();//创建application.yml里的kejiu下的path里面的DLSS
        }
        try {
            //转存到指定位置
            file.transferTo(new File(basePath + filename));//"D:\DLSS\123.jpg"
        } catch (IOException e) {
            e.printStackTrace();
        }

        //System.out.println("文件名"+filename);
        return R.success(filename);
    }

//    1.使用FileInputStream和FileOutputStream：通过创建FileInputStream来读取文件内容，
//    然后使用FileOutputStream将文件内容写入到目标位置，实现文件的上传和下载
    //上传完成之后，马上发出common/download?name=""请求
    //通过输出流向浏览器页面来写回数据(所以不需要返回值了),在浏览器展示图片
    //因为输出流需要通过response来获得
    @GetMapping("/download")//图片下载IO流方式
    public Result download(String name, HttpServletResponse response){
        //System.out.println("下载指定的文件"+basePath + name);
        //需要下载指定的文件
        try {
            //System.out.println("basePath是"+basePath);
            //先从（D:\DLSS\里面）已上传的这个文件来读，输入流：通过输入流来读取文件内容
//            FileInputStream fileInputStream = new FileInputStream
//                    (new File(basePath+name));
            File file = new File(basePath + name);
            FileInputStream fileInputStream = null;
//            System.out.println("file是"+file);
//            System.out.println("file.isFile()是"+file.isFile());
//            System.out.println("file.exists()是"+file.exists());

            if (file.exists() && file.isFile()) {

//                System.out.println("文件存在且是文件");
                fileInputStream = new FileInputStream(file);
            } else {
//                System.out.println("文件不存在: " + name);
                // 返回一个空文件或者其他适当的处理方式
                return new Result(0, "文件"+name+"不存在");
            }

            //输出流，通过输出流将读到的文件内容写回浏览器，在浏览器展示图片(通过response响应对象来get)
            ServletOutputStream outputStream = response.getOutputStream();


            if(name.contains("---")){
                //System.out.println("是图片下载");
                //如果希望浏览器提示用户下载图片而不是直接打开，可以将响应的内容类型改为：
                response.setContentType("application/octet-stream");

                // 使用 split 方法分割字符串
                String[] parts = name.split("---", 2);//最多分割成 2 个部分
                // 获取分割后的第二部分（去掉前面的部分）
                String result = parts.length > 1 ? parts[1] : name;

                //并且添加一个 Content-Disposition 头
                response.setHeader("Content-Disposition", "attachment; filename=\"" + result + "\"");
            }else{
                //System.out.println("是图片回显");
                response.setContentType("image/jpeg");//设置响应回去的是什么类型的文件
            }


            int len = 0;
            //创建一个大小为 1024 字节的字节数组。这个数组用于在读取文件时存储数据。
            //使用缓冲区读取文件的好处在于，它可以减少与文件系统的交互次数，从而提高性能。每次读取 1024 字节（1 KB）数据，
            // 可以有效利用内存，并提高处理效率。如果一次性读取整个文件，尤其是大型文件，会占用大量内存并可能导致程序崩溃。
            byte[] bytes = new byte[1024];
            //每次读，把读到的内容放到bytes数组里面去
            while ((len = fileInputStream.read(bytes))!=-1)//!=-1说明没有读完，就一直读
            {//读完之后,通过输出流向浏览器来写
                outputStream.write(bytes,0,len);//从第一个开始写，写到len这么长
                outputStream.flush();//写完之后通过flush()来刷新
            }
            //关闭资源
            outputStream.close();
            fileInputStream.close();
         } catch (Exception e) {//FileNotFoundException捕获小的异常，Exception捕获大的异常
            e.printStackTrace();
        }
//        return "http://localhost:8083/common/download?name=" + name;
        return null;
    }
}
